// Package common_cos: 对外提供COS对象存储的能力.
// @author: mazhenxin.
// @create: 2021-09-14 16:40:11
package common_cos

import (
	"context"
	"errors"
	"log"
	"net/http"
	"net/url"
	"os"

	"gitee.com/zhenxinma/gocommon/src/common_encode"

	"gitee.com/zhenxinma/gocommon/src/common_static"
	"gitee.com/zhenxinma/gocommon/src/common_time"
	"gitee.com/zhenxinma/gocommon/src/config"

	"github.com/tencentyun/cos-go-sdk-v5"
)

// TODO: 既然是对外进行提供COS能力,那么这里不应该走配置文件，而是根据参数来定.

// CosService 对外暴露,提供给COS能力.
type CosService struct{}

// NewCosService 快速生成CosService对象.
func NewCosService() CosService {
	// 非指针.
	service := CosService{}
	return service
}

var Client *cos.Client

// 初始化init.
func init() {
	// 初始化配置.
	initConfig()
}

func initConfig() {
	config.Init()
}

// Init 初始化cos.Client.
func (r CosService) Init() *cos.Client {

	cosConfig := config.GetConfig().GetStringMapString("cos")
	domain := cosConfig["domain"]
	u, _ := url.Parse(domain)
	b := &cos.BaseURL{BucketURL: u}

	// 对id和key进行解密.
	secretid := common_encode.AesDecrypt(cosConfig["secretid"], cosConfig["encode"])
	secretkey := common_encode.AesDecrypt(cosConfig["secretkey"], cosConfig["encode"])

	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  secretid,
			SecretKey: secretkey,
		},
	})
	Client = client
	return Client
}

// TODO: COS应该支持流或者本地文件形式上传.

// Upload 通过流上传,这里应该和Java中的IO流类似.
func (r CosService) Upload(file *os.File) error {

	if nil == file {
		return errors.New("cos.upload: os.file is nil")
	}

	// 以时间为目录.
	// TODO: 该值必须是唯一的.
	name := common_time.GetNowTimeYmdTs() + "/" + file.Name()
	_, err := Client.Object.Put(context.Background(), name, file, nil)
	if nil != err {
		return err
	}
	// 这里上传成功.
	return nil
}

// UploadLocalFile 上传本地文件.
func (r CosService) UploadLocalFile(path string, fileName string) error {

	if path == "" || fileName == "" {
		return errors.New("upload local file path is nil or filename is nil. ")
	}
	name := common_time.GetNowTimeYmdTs() + "/" + fileName
	res, err := Client.Object.PutFromFile(context.Background(), name, path, nil)
	if nil != err {
		return err
	}
	url := r.GetUploadUrl(res)
	log.Println("upload url: ", url)
	return nil
}

func (r CosService) GetUploadUrl(response *cos.Response) string {
	url := response.Request.URL
	host := url.Host
	path := url.Path
	return common_static.CosUrlPre + host + path
}
